﻿package com.floorplanner.lib3ds
{
	import com.floorplanner.lib3ds.*;
	import com.floorplanner.lib3ds.data.*;
	import com.floorplanner.lib3ds.tracks.*;
	
	/**
	 * Scene graph node.
	 */
	public class Lib3dsNode extends Lib3dsCore
	{
		public static const NO_PARENT:uint = 65535;
				
		public static const UNKNOWN_NODE:uint = 0;
		public static const AMBIENT_NODE:uint = 1;
		public static const OBJECT_NODE:uint  = 2;
		public static const CAMERA_NODE:uint  = 3;
		public static const TARGET_NODE:uint  = 4;
		public static const LIGHT_NODE:uint   = 5;
		public static const SPOT_NODE:uint    = 6;
		
		public var user:Lib3dsUserData;
		public var next:Lib3dsNode;
		public var childs:Lib3dsNode;
		public var parent:Lib3dsNode;
		public var type:uint;
		public var node_id:int;			// short
		public var name:String;			// string[64]
		public var flags1:int;			// short
		public var flags2:int;			// short
		public var parent_id:int;		// short
		public var matrix:Array;		// float[16]
		public var data:Lib3dsNodeData;
		
		/**
		 * 
		 */
		public function Lib3dsNode()
		{
			super( true );
			
			this.data = new Lib3dsNodeData();
			this.user = new Lib3dsUserData();
		}
		
		/**
		 * 
		 * @param	id
		 * @return
		 */
		public function nodeById( id:int ):Lib3dsNode
		{
			var p:Lib3dsNode, q:Lib3dsNode;

			for( p = this.childs; p is Lib3dsNode; p = p.next ) 
			{
				if( p.node_id == id) 
					return p;
		
				q = p.nodeById( id );
				if( q ) 
					return q;
			}
			return null;
		}
		
		public function print( indent:String = "" ):void
		{			
			var p:Lib3dsNode;
			var q:Lib3dsNode;
			
			for( p = this; p is Lib3dsNode; p = p.next ) 
			{
				debug( indent + p.name + " (" + p.node_id + ")" );
				for( q = p.childs; q is Lib3dsNode; q = q.next ) 
				{
					q.print( indent + "->" );
				}
			}
		}
		
		/**
		 * 
		 * @param	io
		 */
		public function read( io:Lib3dsIO ):void
		{
			var c:Lib3dsChunk = Lib3dsChunk.read( io );
			var chunk:uint = 0;
			
			switch (c.chunk) 
			{
				case Lib3dsChunk.AMBIENT_NODE_TAG:
				case Lib3dsChunk.OBJECT_NODE_TAG:
				case Lib3dsChunk.CAMERA_NODE_TAG:
				case Lib3dsChunk.TARGET_NODE_TAG:
				case Lib3dsChunk.LIGHT_NODE_TAG:
				case Lib3dsChunk.SPOTLIGHT_NODE_TAG:
				case Lib3dsChunk.L_TARGET_NODE_TAG:
					break;
				default:
					return;
			}
						
			chunk = c.next( io );
			while( chunk != 0 )
			{
				switch( chunk )
				{
					case Lib3dsChunk.NODE_ID:
						this.node_id = io.readShort();
						debug( "node id: " + this.node_id );
						break;
					
					case Lib3dsChunk.NODE_HDR:
						this.name = io.readString();
						this.flags1 = io.readShort();
						this.flags2 = io.readShort();
						this.parent_id = io.readUnsignedShort();
						debug( "node name: " + this.name + " parent: "+ this.parent_id);
						break;
					
					case Lib3dsChunk.PIVOT:
						if( this.type == OBJECT_NODE )
						{
							this.data.object.pivot = new Array( 3 );
							this.data.object.pivot[0] = io.readFloat();
							this.data.object.pivot[1] = io.readFloat();
							this.data.object.pivot[2] = io.readFloat();
						}
						break;
					
					case Lib3dsChunk.INSTANCE_NAME:
						if( this.type == OBJECT_NODE )
						{
							this.data.object.instance = io.readString();
							debug( "node data.object.instance: " + this.data.object.instance );
						}
						break;
					
					case Lib3dsChunk.BOUNDBOX:
						if( this.type == OBJECT_NODE )
						{
							this.data.object.bbox_min = new Array( 3 );
							this.data.object.bbox_min[0] = io.readFloat();
							this.data.object.bbox_min[1] = io.readFloat();
							this.data.object.bbox_min[2] = io.readFloat();
							
							this.data.object.bbox_max = new Array( 3 );
							this.data.object.bbox_max[0] = io.readFloat();
							this.data.object.bbox_max[1] = io.readFloat();
							this.data.object.bbox_max[2] = io.readFloat();
						}
						break;
					
					case Lib3dsChunk.POS_TRACK_TAG:
						switch( this.type ) 
						{
							case OBJECT_NODE:
								this.data.object.pos_track = new Lib3dsLin3Track();
								this.data.object.pos_track.read( io );
								break;
								
							default:
								break;
						}
						break;
						
					default:
						break;
				}
				
				chunk = c.next( io );
			}
		}
	}
}
